﻿

using Daemon.Data.Substructure.Helpers;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.EntityFrameworkCore.Infrastructure;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Daemon.Model
{
	public partial class ApiDBContent : DbContext
	{

		public ApiDBContent(DbContextOptions<ApiDBContent> options) : base(options)
		{

		}

		public ApiDBContent()
		{

		}

		public DbSet<AdminFile> AdminFile { get; set; }

		public DbSet<SecuredItemGroup> SecuredItemGroup { get; set; }

		public DbSet<SecuredItem> SecuredItem { get; set; }

		public DbSet<RoleSecuredItem> RoleSecuredItem { get; set; }

		public DbSet<ClientConfig> ClientConfig { get; set; }

		public DbSet<UserLog> UserLog { get; set; }

		public DbSet<TokenInfo> TokenInfo { get; set; }

		public DbSet<UserSession> UserSession { get; set; }

		public DbSet<UserRole> UserRole { get; set; }

		public DbSet<AdminRole> AdminRole { get; set; }

		public DbSet<AdminUser> AdminUser { get; set; }

		public DbSet<GenerateConfig> GenerateConfig { get; set; }

		public DbSet<DatabaseConfig> DatabaseConfig { get; set; }
		public DbSet<LogRuleMonitoringField> LogRuleMonitoringField { get; set; }

		public DbSet<LogEntityEventTrackedChange> LogEntityEventTrackedChange { get; set; }

		public DbSet<LogRuleCalculatedField> LogRuleCalculatedField { get; set; }

		public DbSet<LogEntityHardcodedValue> LogEntityHardcodedValue { get; set; }

		public DbSet<LogRule> LogRule { get; set; }

		public DbSet<LogEntityEvent> LogEntityEvent { get; set; }

		public DbSet<LogEntry> LogEntry { get; set; }

		public DbSet<LogEntityMeta> LogEntityMeta { get; set; }

		public DbSet<LogEntityFKMeta> LogEntityFKMeta { get; set; }

		public DbSet<LogRuleReport> LogRuleReport { get; set; }

		public DbSet<AdminDictionary> AdminDictionary { get; set; }

		public DbSet<FormTemplate> FormTemplate { get; set; }

		public DbSet<RoleApplication> RoleApplication { get; set; }

		public DbSet<Application> Application { get; set; }

		public DbSet<CommonCity> CommonCity { get; set; }

		protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
		{
			optionsBuilder.ReplaceService<IModelCacheKeyFactory, DynamicModelCacheKeyFactory>();
		}

		public override int SaveChanges()
		{
			var entities = ChangeTracker.Entries().ToArray();
			var addedEntities = GetEntities(entities.Where(p => p.State == EntityState.Added));
			var changedEntities = GetEntities(entities.Where(p => p.State == EntityState.Modified));
			var deletedEntities = GetEntities(entities.Where(p => p.State == EntityState.Deleted));
			var result = base.SaveChanges();

			if (deletedEntities.Any())
			{
				NotificationHelper.Instance.OnEntitiesDeleted?.Invoke(deletedEntities);
			}

			if (addedEntities.Any())
			{
				NotificationHelper.Instance.OnEntitiesAdded?.Invoke(addedEntities);
			}

			if (changedEntities.Any())
			{
				NotificationHelper.Instance.OnEntitiesChanged?.Invoke(changedEntities);
			}
			return result;
		}

		private Dictionary<Type, List<object>> GetEntities(IEnumerable<EntityEntry> sourceEntities)
		{
			var entitiesDict = new Dictionary<Type, List<object>>();

			foreach (var entity in sourceEntities.Select(r => r.Entity))
			{
				var entityType = entity.GetType();
				if (!entitiesDict.TryGetValue(entityType, out List<object> list))
				{
					list = new List<object>() { entity };
					entitiesDict.Add(entityType, list);
					continue;
				}

				list.Add(entity);
			}

			return entitiesDict;
		}
	}

	public class ApplicationContextDbFactory : IDesignTimeDbContextFactory<ApiDBContent>
	{
		ApiDBContent IDesignTimeDbContextFactory<ApiDBContent>.CreateDbContext(string[] args)
		{
			var optionsBuilder = new DbContextOptionsBuilder<ApiDBContent>();
			string connectionStr = "Server=127.0.0.1;port=3307;Database=blogtest;uid=root;pwd=123456;pooling=true;CharSet=utf8";
			optionsBuilder.UseMySql<ApiDBContent>(connectionStr, Microsoft.EntityFrameworkCore.ServerVersion.Parse("5.7.27-log")).ReplaceService<IModelCacheKeyFactory, DynamicModelCacheKeyFactory>().UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);

			return new ApiDBContent(optionsBuilder.Options);
		}
	}

	//class SchemaModelCacheFactory : IModelCacheKeyFactory
	//{
	//    public object Create(DbContext context) => new SchemaModelCache(context);
	//}


	//class SchemaModelCache : ModelCacheKey
	//{
	//    readonly string _schema;
	//    public SchemaModelCache(DbContext context) : base(context)
	//    {
	//        _schema = (context as ApiDBContent)?.CurrentScheme
	//    }
	//}
	//public class DynamicModelCacheKeyFactory : IModelCacheKeyFactory
	//{
	//    public object Create(DbContext context)
	//    {
	//        if (context is ApiDBContent apiDbContent)
	//        {
	//            return (context.GetType());
	//        }
	//        return context.GetType();
	//    }
	//}
}
